﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using CthulhuDomain;
using CthulhuDomain.GameEntities;
using CthulhuDomain.Services;
using CthulhuDomain.StageManagement;
using Microsoft.Pex.Framework;
using Microsoft.Pex.Framework.Validation;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Invaders.Test.Factories.GameEntities
{
  [TestClass]
  public partial class DomainEntityMatrixFixture
  {
    private static ContentManager contentManager;
    private SpriteBatchAdapter spriteBatch;
    private GameServiceManager gameServiceManager;

    [TestInitialize]
    public void TestInitialize() {
      var gd = new MockedGraphicsDeviceService(DeviceType.Hardware, GraphicsProfile.HiDef);
      gd.CreateDevice();

      string activeConfinguration;
#if DEBUG
      activeConfinguration = "Debug";
#else
      activeConfinguration = "Release";

#endif
      spriteBatch = new SpriteBatchAdapter(gd.GraphicsDevice);
      contentManager = new ContentManager(gd.ServiceProvider) {
        RootDirectory = Path.GetFullPath(string.Format("../../../CthulhuInvaders/bin/x86/{0}/Content/", activeConfinguration))
      };

      gameServiceManager = new GameServiceManager(new GameAdapter(new Game()), new ContentManagerAdapter(contentManager), spriteBatch, new RectangleAdapter(0, 0, 300, 300));
    }

    [TestCleanup]
    public void MyTestCleanup() {
      contentManager = null;
      spriteBatch = null;
      gameServiceManager = null;
    }

    [PexMethod(MaxBranches = 40000)]
    [PexAllowedException(typeof(NullReferenceException))]
    public DomainEntityMatrix Ctor_ByLevel_IsFullyInitialized(int _level) {
      // Arrange
      //var factory = DomainFactory.GetFactory(DomainFactory.eTypeEntity.Cthulhu);
      var _rectangleAdapter = new RectangleAdapter(0, 0, 300, 300);
      var manager = new ContentManagerAdapter(contentManager);
      var matrixConfigurations = manager.LoadSetUp();
      try {
        var level = matrixConfigurations.SingleOrDefault(x => x.ID == _level);
        DomainEntityMatrix matrix = null;
        // Act
        matrix = new DomainEntityMatrix(level.Schema);
        matrix.LoadContent(new ContentManagerAdapter(contentManager), _rectangleAdapter);
        // Assert
        Assert.IsTrue(matrix.EntityCount() > 0);
        Trace.WriteLine(string.Format("Entity Count: {0}", matrix.EntityCount()));
        return matrix;
      }
      catch (Exception exception) {
        Trace.WriteLine(string.Format("Level - {0} - Missing configuration", _level));
      }
      return null;
    }

    [PexMethod(MaxBranches = 40000)]
    [PexAllowedException(typeof(NullReferenceException))]
    public void GetElement_00_ShouldNotBeNull(int _level)
    {
      // Arrange
      var matrix = Ctor_ByLevel_IsFullyInitialized(_level);
      // Act
      try
      {
        var element = matrix.GetElement(0, 0);
        // Assert
        Assert.IsNotNull(element);
        Trace.WriteLine(string.Format("Level - {0} - Test passsed",_level));
      }
      catch (Exception exception)
      {
        ;
      }
    }

    [PexMethod(MaxBranches = 40000)]
    [PexAllowedException(typeof(NullReferenceException))]
    public void GetDamage_EntityXY_ShouldBeGreaterZero(int _level)
    {
      // Arrange
      PexAssume.IsTrue(_level > 0);
      var matrix = Ctor_ByLevel_IsFullyInitialized(_level);
      
      // Act
      int x = PexChoose.ValueFromRange("x", 0, matrix.XLength);
      int y = PexChoose.ValueFromRange("y", 0, matrix.YLength);
      PexObserve.Value("x",x);
      PexObserve.Value("y",y);
      var damage = matrix.GetDamage(x, y);
      // Assert
      Assert.IsTrue(damage > 0);
    }

    [PexMethod,ExpectedException(typeof(InvalidEnumArgumentException))]
    public void GetFactory_TypeFactoryEqualZero_ThrowInvalidArgumentException()
    {
      // Arrange
      // Act
      try
      {
        var factory = EntityStateFactory.GetFactory(DomainFactory.eTypeEntity.None);
      }
      catch (Exception e)
      {
        Trace.WriteLine(e);
      }
      // Assert
    }

  }
}
